/*
 * @(#)GetAllRunner.java
 * Date 2013-09-06
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.query.es;

import java.util.HashMap;
import java.util.Map;

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;

import us.hornerscorners.lamppost.exception.ServiceActionException;

import us.hornerscorners.lamppost.ihecommon.config.IHEConfig;

import us.hornerscorners.lamppost.ihecommon.service.ElasticSearchSource;

import us.hornerscorners.lamppost.model.common.PersistableModelType;

import us.hornerscorners.lamppost.registry.constant.QueryField;
import us.hornerscorners.lamppost.registry.constant.QuerySlotName;

import us.hornerscorners.lamppost.registry.model.QueryRequest;
import us.hornerscorners.lamppost.registry.model.QueryResponse;
import us.hornerscorners.lamppost.registry.model.RegistryObjects;

import us.hornerscorners.lamppost.registry.transformer.model.CodedElementTransformer;
import us.hornerscorners.lamppost.registry.transformer.model.PatientIdentifierTransformer;

import us.hornerscorners.lamppost.registry.utils.RegistryObjectsUtils;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-09-06
 * @author         Jim Horner
 */
public class GetAllRunner extends AbstractQueryRunner {

    /**
     * Constructs ...
     *
     *
     * @param config
     * @param elasticSearchSource
     * @param codedElementTransformer
     * @param patientIdentifierTransformer
     */
    public GetAllRunner(IHEConfig config, ElasticSearchSource elasticSearchSource,
                        CodedElementTransformer codedElementTransformer,
                        PatientIdentifierTransformer patientIdentifierTransformer) {

        super(config, elasticSearchSource, codedElementTransformer,
              patientIdentifierTransformer);

    }

    /**
     * Method description
     *
     *
     * @param request
     *
     * @return
     *
     */
    @Override
    public Map<PersistableModelType, QueryBuilder> createQuery(QueryRequest request) {

        Map<PersistableModelType, QueryBuilder> result = new HashMap<>();

        BoolQueryBuilder queryDocs = QueryBuilders.boolQuery();

        result.put(PersistableModelType.DocumentEntry, queryDocs);

        // patient id (required)
        queryDocs.must(createPatientIdentifierQuery(request, QuerySlotName.PatientId,
                QueryField.DocumentEntryPatientIdRoot,
                QueryField.DocumentEntryPatientIdExtension));

        // availability status (required)
        queryDocs.must(createStringQuery(request, QuerySlotName.XDSDocumentEntryStatus,
                                         QueryField.DocumentEntryAvailabilityStatus));

        // confidentiality code
        if (request.hasValues(QuerySlotName.XDSDocumentEntryConfidentialityCode)) {

            queryDocs.must(createCodedElementQuery(request,
                    QuerySlotName.XDSDocumentEntryConfidentialityCode,
                    QueryField.DocumentEntryConfidentialityCodesCode,
                    QueryField.DocumentEntryConfidentialityCodesScheme));
        }

        if (request.hasValues(QuerySlotName.XDSDocumentEntryConfidentialityCodeScheme)) {

            queryDocs.must(
                createStringQuery(
                    request, QuerySlotName.XDSDocumentEntryConfidentialityCodeScheme,
                    QueryField.DocumentEntryConfidentialityCodesScheme));
        }

        // format code
        if (request.hasValues(QuerySlotName.XDSDocumentEntryFormatCode)) {

            queryDocs.must(createCodedElementQuery(request,
                    QuerySlotName.XDSDocumentEntryFormatCode,
                    QueryField.DocumentEntryFormatCodeCode,
                    QueryField.DocumentEntryFormatCodeScheme));
        }

        if (request.hasValues(QuerySlotName.XDSDocumentEntryFormatCodeScheme)) {

            queryDocs.must(
                createStringQuery(
                    request, QuerySlotName.XDSDocumentEntryFormatCodeScheme,
                    QueryField.DocumentEntryFormatCodeScheme));
        }

        BoolQueryBuilder queryFolders = QueryBuilders.boolQuery();

        result.put(PersistableModelType.Folder, queryFolders);

        // patient id (required)
        queryFolders.must(createPatientIdentifierQuery(request, QuerySlotName.PatientId,
                QueryField.FolderPatientIdRoot, QueryField.FolderPatientIdExtension));

        // availability status (required)
        queryFolders.must(createStringQuery(request, QuerySlotName.XDSFolderStatus,
                QueryField.FolderAvailabilityStatus));

        BoolQueryBuilder querySubSets = QueryBuilders.boolQuery();

        result.put(PersistableModelType.SubmissionSet, querySubSets);

        // patient id (required)
        querySubSets.must(createPatientIdentifierQuery(request, QuerySlotName.PatientId,
                QueryField.SubmissionSetPatientIdRoot,
                QueryField.SubmissionSetPatientIdExtension));

        // availability status (required)
        querySubSets.must(createStringQuery(request,
                QuerySlotName.XDSSubmissionSetStatus,
                QueryField.SubmissionSetAvailabilityStatus));

        return result;
    }

    /**
     * Method description
     *
     *
     * @param request
     *
     * @return
     *
     * @throws ServiceActionException
     */
    @Override
    public QueryResponse run(QueryRequest request) throws ServiceActionException {

        QueryResponse result = super.run(request);

        RegistryObjects rol = result.getRegistryObjects();

        rol.addAllAssociations(RegistryObjectsUtils.pullAllAssociations(rol));

        return result;
    }
}
